<!DOCTYPE html>
<html class="writer-html5" lang="zh" >
<head>
  <meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Ch4-3 片段着色器 &mdash; EasyVulkan</title>
      <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
      <link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
      <link rel="stylesheet" href="_static/theme.css" type="text/css" />
  <!--[if lt IE 9]>
    <script src="_static/js/html5shiv.min.js"></script>
  <![endif]-->
  
        <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
        <script src="_static/jquery.js"></script>
        <script src="_static/underscore.js"></script>
        <script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
        <script src="_static/doctools.js"></script>
    <script src="_static/js/theme.js"></script>
    <link rel="index" title="索引" href="genindex.html" />
    <link rel="search" title="搜索" href="search.html" />
    <link rel="next" title="Ch4-4 几何着色器" href="Ch4-4%20%E5%87%A0%E4%BD%95%E7%9D%80%E8%89%B2%E5%99%A8.html" />
    <link rel="prev" title="Ch4-2 顶点着色器" href="Ch4-2%20%E9%A1%B6%E7%82%B9%E7%9D%80%E8%89%B2%E5%99%A8.html" /> 
</head>

<body class="wy-body-for-nav"> 
  <div class="wy-grid-for-nav">
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search" >
            <a href="index.html" class="icon icon-home"> EasyVulkan
            <img src="_static/logo1.png" class="logo" alt="Logo"/>
          </a>
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="search.html" method="get">
    <input type="text" name="q" placeholder="在文档中搜索" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>
        </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
              <p class="caption" role="heading"><span class="caption-text">第一章 初始化</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch1-0%20%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C.html">Ch1-0 准备工作</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch1-1%20%E5%88%9B%E5%BB%BAGLFW%E7%AA%97%E5%8F%A3.html">Ch1-1 创建GLFW窗口</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch1-2%20%E5%88%9D%E5%A7%8B%E5%8C%96%E6%B5%81%E7%A8%8B.html">Ch1-2 初始化流程</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch1-3%20%E5%88%9B%E5%BB%BAVK%E5%AE%9E%E4%BE%8B%E4%B8%8E%E9%80%BB%E8%BE%91%E8%AE%BE%E5%A4%87.html">Ch1-3 创建VK实例与逻辑设备</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch1-4%20%E5%88%9B%E5%BB%BA%E4%BA%A4%E6%8D%A2%E9%93%BE.html">Ch1-4 创建交换链</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第二章 绘制一个三角形</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch2-0%20%E4%BB%A3%E7%A0%81%E6%95%B4%E7%90%86%E5%8F%8A%E4%B8%80%E4%BA%9B%E8%BE%85%E5%8A%A9%E7%B1%BB.html">Ch2-0 代码整理及一些辅助类</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch2-1%20Rendering%20Loop.html">Ch2-1 Rendering Loop</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch2-2%20%E5%88%9B%E5%BB%BA%E6%B8%B2%E6%9F%93%E9%80%9A%E9%81%93%E5%92%8C%E5%B8%A7%E7%BC%93%E5%86%B2.html">Ch2-2 创建渲染通道和帧缓冲</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch2-3%20%E5%88%9B%E5%BB%BA%E7%AE%A1%E7%BA%BF%E5%B9%B6%E7%BB%98%E5%88%B6%E4%B8%89%E8%A7%92%E5%BD%A2.html">Ch2-3 创建管线并绘制三角形</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第三章 纵观Vulkan</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch3-1%20%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD.html">Ch3-1 同步原语</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-2%20%E5%9B%BE%E5%83%8F%E4%B8%8E%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch3-2 图像与缓冲区</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-3%20%E7%AE%A1%E7%BA%BF%E5%B8%83%E5%B1%80%E5%92%8C%E7%AE%A1%E7%BA%BF.html">Ch3-3 管线布局和管线</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-4%20%E6%B8%B2%E6%9F%93%E9%80%9A%E9%81%93%E5%92%8C%E5%B8%A7%E7%BC%93%E5%86%B2.html">Ch3-4 渲染通道和帧缓冲</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-5%20%E5%91%BD%E4%BB%A4%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch3-5 命令缓冲区</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-6%20%E6%8F%8F%E8%BF%B0%E7%AC%A6.html">Ch3-6 描述符</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-7%20%E9%87%87%E6%A0%B7%E5%99%A8.html">Ch3-7 采样器</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch3-8%20%E6%9F%A5%E8%AF%A2.html">Ch3-8 查询</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第四章 着色器</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="Ch4-1%20%E7%9D%80%E8%89%B2%E5%99%A8%E6%A8%A1%E7%BB%84.html">Ch4-1 着色器模组</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch4-2%20%E9%A1%B6%E7%82%B9%E7%9D%80%E8%89%B2%E5%99%A8.html">Ch4-2 顶点着色器</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Ch4-3 片段着色器</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#id1">片段着色器的内置输入</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#gl-fragcoord">gl_FragCoord</a></li>
<li class="toctree-l3"><a class="reference internal" href="#gl-frontfacing">gl_FrontFacing</a></li>
<li class="toctree-l3"><a class="reference internal" href="#gl-pointcoord">gl_PointCoord</a></li>
<li class="toctree-l3"><a class="reference internal" href="#gl-samplemaskin">gl_SampleMaskIn</a></li>
<li class="toctree-l3"><a class="reference internal" href="#gl-helperinvocation">gl_HelperInvocation</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#id2">片段着色器的内置输出</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#gl-samplemask">gl_SampleMask</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#early-fragment-test">Early Fragment Test</a></li>
<li class="toctree-l2"><a class="reference internal" href="#dual-source-blending">Dual-source Blending</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="Ch4-4%20%E5%87%A0%E4%BD%95%E7%9D%80%E8%89%B2%E5%99%A8.html">Ch4-4 几何着色器</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第五章 封装常用对象</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch5-0%20VKBase%2B.h.html">Ch5-0 VKBase+.h</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch5-1%20%E5%90%84%E7%A7%8D%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch5-1 各种缓冲区</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch5-2%202D%E8%B4%B4%E5%9B%BE%E5%8F%8A%E7%94%9F%E6%88%90Mipmap.html">Ch5-2 2D贴图及生成Mipmap</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch5-3%202D%E8%B4%B4%E5%9B%BE%E6%95%B0%E7%BB%84.html">Ch5-3 2D贴图数组</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第六章 进阶Vulkan</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch6-0%20%E4%BD%BF%E7%94%A8%E6%96%B0%E7%89%88%E6%9C%AC%E7%89%B9%E6%80%A7.html">Ch6-0 使用新版本特性</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch6-1%20%E6%97%A0%E5%9B%BE%E5%83%8F%E5%B8%A7%E7%BC%93%E5%86%B2.html">Ch6-1 无图像帧缓冲</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch6-2%20%E5%8A%A8%E6%80%81%E6%B8%B2%E6%9F%93.html">Ch6-2 动态渲染</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第七章 基础示例</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch7-1%20%E5%88%9D%E8%AF%86%E9%A1%B6%E7%82%B9%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch7-1 初识顶点缓冲区</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-2%20%E5%88%9D%E8%AF%86%E7%B4%A2%E5%BC%95%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch7-2 初识索引缓冲区</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-3%20%E5%88%9D%E8%AF%86%E5%AE%9E%E4%BE%8B%E5%8C%96%E7%BB%98%E5%88%B6.html">Ch7-3 初识实例化绘制</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-4%20%E5%88%9D%E8%AF%86Push%20Constant.html">Ch7-4 初识Push Constant</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-5%20%E5%88%9D%E8%AF%86Uniform%E7%BC%93%E5%86%B2%E5%8C%BA.html">Ch7-5 初识Uniform缓冲区</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-6%20%E6%8B%B7%E8%B4%9D%E5%9B%BE%E5%83%8F%E5%88%B0%E5%B1%8F%E5%B9%95.html">Ch7-6 拷贝图像到屏幕</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch7-7%20%E4%BD%BF%E7%94%A8%E8%B4%B4%E5%9B%BE.html">Ch7-7 使用贴图</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">第八章 简单示例</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ch8-1%20%E7%A6%BB%E5%B1%8F%E6%B8%B2%E6%9F%93.html">Ch8-1 离屏渲染</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch8-2%20%E6%B7%B1%E5%BA%A6%E6%B5%8B%E8%AF%95%E5%92%8C%E6%B7%B1%E5%BA%A6%E5%8F%AF%E8%A7%86%E5%8C%96.html">Ch8-2 深度测试和深度可视化</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch8-3%20%E5%BB%B6%E8%BF%9F%E6%B8%B2%E6%9F%93.html">Ch8-3 延迟渲染</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch8-4%20%E9%A2%84%E4%B9%98Alpha.html">Ch8-4 预乘Alpha</a></li>
<li class="toctree-l1"><a class="reference internal" href="Ch8-5%20sRGB%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4%E4%B8%8E%E5%BC%80%E5%90%AFHDR.html">Ch8-5 sRGB色彩空间与开启HDR</a></li>
</ul>
<p class="caption" role="heading"><span class="caption-text">附录</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="Ap1-1%20%E8%BF%90%E8%A1%8C%E6%9C%9F%E7%BC%96%E8%AF%91GLSL.html">Ap1-1 运行期编译GLSL</a></li>
</ul>

        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" >
          <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
          <a href="index.html">EasyVulkan</a>
      </nav>

      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="Page navigation">
  <ul class="wy-breadcrumbs">
      <li><a href="index.html" class="icon icon-home"></a> &raquo;</li>
      <li>Ch4-3 片段着色器</li>
      <li class="wy-breadcrumbs-aside">
      </li>
  </ul>
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
             
  <section id="ch4-3">
<h1>Ch4-3 片段着色器<a class="headerlink" href="#ch4-3" title="Permalink to this heading"></a></h1>
<p>
    片段着色器（fragment shader）是图形管线中的一个着色器，用于处理片段（即像素）的颜色，也可以改变片段或采样点的深度值。
    <br>
    对于一个有片段着色器的图形管线，片段着色器是管线中最后执行的着色器。
</p>
<p>
    片段着色器对每个被图元（即点、线、三角形）覆盖的像素，或（多重采样中开启sample shading时的）采样点发生调用。
    <br>
    注：具体而言，片段着色器被定义为逐片段调用至少一次，而开启sample shading后，可能会发生额外调用（<a href="https://renderdoc.org/vkspec_chunked/chap29.html#fragops-shader">官方文档中的说法见此</a>）。
    <br>
    ↑不管你干什么，最好不要依赖于“逐片段调用”这一说法，若Vulkan的实现能判断某个片段最终会被后续其他片段覆盖（即不影响最终渲染结果），那么可能直接不对其执行片段着色器。
</p><section id="id1">
<h2>片段着色器的内置输入<a class="headerlink" href="#id1" title="Permalink to this heading"></a></h2>
<p>
    用GLSL编写的片段着色器有以下内置输入：
</p>
<pre class="code">
<span class="type">vec4</span> gl_FragCoord;
<span class="kw">bool</span> gl_FrontFacing;
<span class="kw">float</span> gl_ClipDistance[];
<span class="kw">float</span> gl_CullDistance[];

<span class="type">vec2</span> gl_PointCoord;

<span class="kw">int</span> gl_SampleID;
<span class="type">vec2</span> gl_SamplePosition;
<span class="kw">int</span> gl_SampleMaskIn[];

<span class="kw">int</span> gl_PrimitiveID;

<span class="kw">int</span> gl_Layer;
<span class="kw">int</span> gl_ViewportIndex;

<span class="kw">bool</span> gl_HelperInvocation;
</pre>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p>全局变量</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="type">vec4</span> gl_FragCoord</p></td>
            <td><p>当前采样点在屏幕空间内的坐标</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">bool</span> gl_FrontFacing</p></td>
            <td><p>表示生成当前片段的图元是正面还是还反面</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="kw">float</span> gl_ClipDistance[]</p></td>
            <td><p>自定义剪裁参数</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">float</span> gl_CullDistance[]</p></td>
            <td><p>自定义剔除参数</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">vec2</span> gl_PointCoord</p></td>
            <td><p>若生成当前片段的图元是点，表示该片段在点内的归一化坐标（点是有大小的）</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">int</span> gl_SampleID</p></td>
            <td><p>当前采样点的索引</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="type">vec2</span> gl_SamplePosition</p></td>
            <td><p>当前采样点在像素内的归一化坐标，x和y的范围为[0,1]</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">int</span> gl_SampleMaskIn[]</p></td>
            <td><p>当前采样点的位遮罩</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="kw">int</span> gl_PrimitiveID</p></td>
            <td><p>生成当前片段的图元的索引</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">int</span> gl_Layer</p></td>
            <td><p>当前片段所在的图层索引（用于使用了多层帧缓冲的情况）</p></td>
        </tr>
        <tr class="row-even">
            <td><p><span class="kw">int</span> gl_ViewportIndex</p></td>
            <td><p>当前片段所在的视口索引（用于开启了多视口（multiViewport）的情况）</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">bool</span> gl_HelperInvocation</p></td>
            <td><p>说明本次对片段着色器的调用是否是一次辅助调用</p></td>
        </tr>
    </tbody>
</table>
<p>
    gl_ClipDistance和gl_CullDistance由先前的管线阶段中输出的同名内置输出插值而来（插值方式考虑透视），语义参见<a class="reference internal" href="Ch4-2%20%E9%A1%B6%E7%82%B9%E7%9D%80%E8%89%B2%E5%99%A8.html#id2">顶点着色器的内置输出</a>。
    <br>
    gl_Layer和gl_ViewportIndex的语义参见<a class="reference internal" href="Ch4-4%20%E5%87%A0%E4%BD%95%E7%9D%80%E8%89%B2%E5%99%A8.html#id2">几何着色器的内置输出</a>。
</p><section id="gl-fragcoord">
<h3>gl_FragCoord<a class="headerlink" href="#gl-fragcoord" title="Permalink to this heading"></a></h3>
<p>
    gl_FragCoord的x和y坐标是<strong>屏幕空间内的非归一化坐标</strong>，在没有多重采样的情况下，坐标选取各个像素的中心位置即数值以.5结尾，以左上角为原点，左上角像素坐标为(0.5, 0.5)。
    <br>
    从OpenGL转来的程序员注意，OpenGL中默认以左下角为原点，并且Vulkan中不再支持pixel_center_integer修饰符。
    <br>
    多重采样时，gl_FragCoord.x和gl_FragCoord.y精确到片段内部采样点的坐标。
    <br>
    gl_FragCoord.z是将NDC坐标的z分量进行视口变换后得到的深度值。
    <br>
    gl_FragCoord.w为对先前阶段中输出的gl_Position.w插值得到的数值的倒数。
</p></section>
<section id="gl-frontfacing">
<h3>gl_FrontFacing<a class="headerlink" href="#gl-frontfacing" title="Permalink to this heading"></a></h3>
<p>
    gl_FrontFacing根据三角形顶点的手性决定正反，而顺时针还是逆时针为正，由<a href="https://renderdoc.org/vkspec_chunked/chap27.html#VkPipelineRasterizationStateCreateInfo">VkPipelineRasterizationStateCreateInfo</a>::frontFace规定。
    <br>
    如果生成当前片段的图元是三角形正面、线或点，则为<span class="kw">true</span>。
</p></section>
<section id="gl-pointcoord">
<h3>gl_PointCoord<a class="headerlink" href="#gl-pointcoord" title="Permalink to this heading"></a></h3>
<p>
    绘制点绘制出的是正方形，点的大小由先前阶段中的gl_PointSize指定。
    <br>
    gl_PointCoord以正方形左上角为原点，因是归一化坐标，x和y的范围为[0,1]。
</p></section>
<section id="gl-samplemaskin">
<h3>gl_SampleMaskIn<a class="headerlink" href="#gl-samplemaskin" title="Permalink to this heading"></a></h3>
<p>
    gl_SampleMaskIn中每个bit对应相应索引的采样点，因此其数组元素个数亦取决于采样点个数，<span class="kw">int</span>的长度为32个bit，因此32xMSAA及以下时gl_SampleMaskIn中有一个元素，64xMSAA时有两个元素。
</p>
<p>
    （阅读以下文字前请先阅读<a class="reference internal" href="Ch3-3%20%E7%AE%A1%E7%BA%BF%E5%B8%83%E5%B1%80%E5%92%8C%E7%AE%A1%E7%BA%BF.html#vkpipelinemultisamplestatecreateinfo">Ch3-3 管线布局和管线一节中关于VkPipelineMultisampleStateCreateInfo的说明</a>）
    <br>
    开启sample shading时，一个采样点的gl_SampleMaskIn[0]的数值为<code>coverage_mask & sample_mask & (1 << gl_SampleID)</code>。以4xMSAA为例，若四个采样点皆被图元覆盖且没有指定sample mask，那么各个采样点的gl_SampleMaskIn[0]的数值即<code>1 << gl_SampleID</code>。
    <br>
    未开sample shading时，一个采样点的gl_SampleMaskIn[0]的数值为<code>coverage_mask & sample_mask</code>。以4xMSAA为例，若四个采样点皆被图元覆盖且没有指定sample mask，则四个采样点的gl_SampleMaskIn[0]的数值皆为0b1111。
</p></section>
<section id="gl-helperinvocation">
<h3>gl_HelperInvocation<a class="headerlink" href="#gl-helperinvocation" title="Permalink to this heading"></a></h3>
<p>
    在quad group操作时，可能需要进行额外的辅助调用（helper invocation）。
    <br>
    求偏导数需要涉及quad group操作，因为glsl中的函数<span class="fn">dFdx</span>(...)和<span class="fn">dFdy</span>(...)是对2x2像素的单元（称为一个quad）实行的。
    <br>
    然而，仅栅格化后的被片段覆盖的区域，很有可能在边缘上凑不出这样的2x2像素单元，于是可能就有必要对没被片元覆盖的相邻位置执行辅助调用（helper invocation）来凑出一个quad。
    <br>
    在辅助调用中，不应写入storage缓冲区，也不应使用原子性操作，因此有判别本次调用是否是辅助调用的必要，gl_HelperInvocation正是因此存在的。
</p></section>
</section>
<section id="id2">
<h2>片段着色器的内置输出<a class="headerlink" href="#id2" title="Permalink to this heading"></a></h2>
<p>
    用GLSL编写的片段着色器有以下内置输出：
</p>
<pre class="code">
<span class="kw">float</span> gl_FragDepth;
<span class="kw">int</span> gl_SampleMask[];
</pre>
<table class="docutils align-default">
    <colgroup>
        <col style="width: 30%" />
        <col style="width: 70%" />
    </colgroup>
    <thead>
        <tr class="row-odd">
            <th class="head" colspan="2"><p>全局变量</p></th>
        </tr>
    </thead>
    <tbody>
        <tr class="row-even">
            <td><p><span class="kw">float</span> gl_FragDepth</p></td>
            <td><p>当前片段的深度</p></td>
        </tr>
        <tr class="row-odd">
            <td><p><span class="kw">int</span> gl_SampleMask[]</p></td>
            <td><p>当前采样点的位遮罩</p></td>
        </tr>
    </tbody>
</table>
<p>
    若未曾使用gl_FragDepth（指着色器代码中没出现过），则gl_FragDepth自动取得gl_FragCoord.z的值。
    <br>
    若未曾使用gl_SampleMask（指着色器代码中没出现过），则gl_SampleMask自动取得gl_SampleMaskIn数组的值。
    <br>
    注意，若在if语句的一个分支中写入了gl_FragDepth或gl_SampleMask，那么哪怕不执行该分支，gl_FragDepth或gl_SampleMask也无法自动取得相应值。
</p><section id="gl-samplemask">
<h3>gl_SampleMask<a class="headerlink" href="#gl-samplemask" title="Permalink to this heading"></a></h3>
<p>
    最终，采样点会有一个或0或1的系数，由gl_SampleMask中相应的bit与gl_SampleMaskIn中相应的bit位与决定。
    <br>
    这里所谓的系数更准确地说是在执行过片段着色器后，最终得到的各个采样点的coverage。我不想在这里解释额外的概念，让我用一个具体的例子说明gl_SampleMask的影响：
    <br>
    如前文所说，对于4xMSAA，<strong>开启sample shading时</strong>，若四个采样点皆被图元覆盖且没有应用sample mask，索引为0的采样点获得的gl_SampleMaskIn[0]为0b0001，索引为1的采样点获得的gl_SampleMaskIn[0]为0b0010，依次类推。那么：
    <br>
    如果输出的gl_SampleMask[0]，对应从0开始的各个索引的采样点，依次为0b0001、0b0010、0b0100、0b1000，则最后呈现出的效果与不写入gl_SampleMask时一致。
    <br>
    如果输出的gl_SampleMask[0]，对应从0开始的各个索引的采样点，0b1000、0b0100、0b0010、0b0001，则最后的解析得到的颜色为<code><span class="type">vec4</span>(0,0,0,0)</code>。
    <br>
    如果输出的gl_SampleMask[0]，对应从0开始的各个索引的采样点，皆为0b0001，用<span class="var">colorSample0</span>指代索引为0的采样点，则最后的解析得到的颜色为<code><span class="type">vec4</span>(colorSample0.rgb, colorSample0.a / 4)</code>，这个值相当于一个不透明的像素与三个完全透明的像素的平均。
</p></section>
</section>
<section id="early-fragment-test">
<h2>Early Fragment Test<a class="headerlink" href="#early-fragment-test" title="Permalink to this heading"></a></h2>
<p>
    早期片段测试（early fragment test）发生在执行片段着色器前，若片段着色器没有诸如写入storage缓冲区等副作用，也不会更改片段的深度值（gl_FragDepth），那么很显然，完全有理由在执行片段着色器前，进行深度范围测试、深度测试和模板测试，以避免不必要的片段着色器调用。
    <br>
    Vulkan的实现有可能隐式地帮你开启早期片段测试，你也可以在片段着色器中显式地开启它：
</p>
<pre class="code">
<span class="kw">layout</span>(early_fragment_tests) <span class="kw">in</span>;
</pre></section>
<section id="dual-source-blending">
<h2>Dual-source Blending<a class="headerlink" href="#dual-source-blending" title="Permalink to this heading"></a></h2>
<p>
    有这四个混色因子（<a href="https://renderdoc.org/vkspec_chunked/chap29.html#VkBlendFactor">VkBlendFactor</a>）的枚举项：
    <br>
    <span class="enum">VK_BLEND_FACTOR_SRC1_COLOR</span>、
    <br>
    <span class="enum">VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR</span>、
    <br>
    <span class="enum">VK_BLEND_FACTOR_SRC1_ALPHA</span>、
    <br>
    <span class="enum">VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA</span>
</p>
<p>
    若在混色中使用来自SRC1的色值，这种混色方式称为dual-source blending。
    <br>
    片段着色器可以向一个location输出两个色值，写法如下：
</p>
<pre class="code">
<span class="kw">layout</span>(location = 0) <span class="kw">out</span> <span class="type">vec4</span> o_Color;             <span class="cmt">//index为0，对应SRC</span>
<span class="kw">layout</span>(location = 0, index = 1) <span class="kw">out</span> <span class="type">vec4</span> o_Color1; <span class="cmt">//index为1，对应SRC1</span>
</pre></section>
</section>


           </div>
          </div>
          <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer">
        <a href="Ch4-2%20%E9%A1%B6%E7%82%B9%E7%9D%80%E8%89%B2%E5%99%A8.html" class="btn btn-neutral float-left" title="Ch4-2 顶点着色器" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> 上一页</a>
        <a href="Ch4-4%20%E5%87%A0%E4%BD%95%E7%9D%80%E8%89%B2%E5%99%A8.html" class="btn btn-neutral float-right" title="Ch4-4 几何着色器" accesskey="n" rel="next">下一页 <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
    </div>

  <hr/>

  <div role="contentinfo">
    <p>&#169; 版权所有 2021-2025, 葉橙.</p>
  </div>

  利用 <a href="https://www.sphinx-doc.org/">Sphinx</a> 构建，使用了 
    <a href="https://github.com/readthedocs/sphinx_rtd_theme">主题</a>
    由 <a href="https://readthedocs.org">Read the Docs</a>开发.
   

</footer>
        </div>
      </div>
    </section>
  </div>
  <script>
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script> 

</body>
</html>